home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 41 / Amiga Format CD41 (1999-06)(Future Publishing)(GB)[!][issue 1999-07].iso / -seriously_amiga- / programming / other / scm / slib / chez.init < prev    next >
Text File  |  1999-04-19  |  13KB  |  388 lines

  1. ;;;"chez.init" Initialization file for SLIB for Chez Scheme 5.0c -*-scheme-*-
  2. ;;; Authors: dorai@cs.rice.edu (Dorai Sitaram) and Aubrey Jaffer.
  3. ;;;
  4. ;;; This code is in the public domain.
  5.  
  6. ; Adapted to version 5.0c by stone@math.grin.edu (John David Stone) 1997
  7.  
  8. ;; The SOFTWARE-TYPE procedure returns a symbol indicating the generic
  9. ;; operating system type.  UNIX, VMS, MACOS, AMIGA and MS-DOS are
  10. ;; supported.
  11.  
  12. (define software-type
  13.   (lambda () 'unix))
  14.  
  15. ;; The SCHEME-IMPLEMENTATION-TYPE procedure returns a symbol denoting the
  16. ;; Scheme implementation that loads this file.
  17.  
  18. (define scheme-implementation-type
  19.   (lambda () 'chez))
  20.  
  21. ;;; (scheme-implementation-home-page) should return a (string) URL
  22. ;;; (Uniform Resource Locator) for this scheme implementation's home
  23. ;;; page; or false if there isn't one.
  24.  
  25. (define (scheme-implementation-home-page) #f)
  26.  
  27. ;; The SCHEME-IMPLEMENTATION-VERSION procedure returns a string describing
  28. ;; the version of the Scheme implementation that loads this file.
  29.  
  30. (define scheme-implementation-version
  31.   (lambda () "5.0c"))
  32.  
  33. ;; The IMPLEMENTATION-VICINITY procedure returns a string giving the
  34. ;; pathname of the directory that includes any auxiliary files used by this
  35. ;; Scheme implementation.
  36.  
  37. (define implementation-vicinity
  38.   (lambda () "/usr/local/chez/5.0c/"))
  39.  
  40. ;; The GETENV returns the value of a shell environment variable.
  41.  
  42. ;; In some implementations of Chez Scheme, this can be done with foreign
  43. ;; procedures.  However, I [JDS] am using the HP version, which does not
  44. ;; support them, so a different approach is needed.
  45. ;;
  46. ;; Here's the version that doesn't work on HPs:
  47. ;;
  48. ;; (provide-foreign-entries '("getenv"))
  49. ;; 
  50. ;; (define getenv
  51. ;;   (foreign-procedure "getenv"
  52. ;;     (string) string))
  53. ;;
  54. ;; And here's a version that parses the value out of the output of the
  55. ;; /bin/env command:
  56.  
  57. (define getenv
  58.   (lambda (env-var)
  59.     (let ((env-port (car (process "exec /bin/env")))
  60.           (read-line
  61.            (lambda (source)
  62.              (let ((next (peek-char source)))
  63.                (if (eof-object? next)
  64.                    next
  65.                    (let loop ((ch (read-char source))
  66.                               (so-far '()))
  67.                      (if (or (eof-object? ch)
  68.                              (char=? ch #\newline))
  69.                          (apply string (reverse so-far))
  70.                          (loop (read-char source) (cons ch so-far))))))))
  71.           (position-of-copula
  72.            (lambda (str)
  73.              (let ((len (string-length str)))
  74.                (do ((position 0 (+ position 1)))
  75.                    ((or (= position len)
  76.                         (char=? (string-ref str position) #\=))
  77.                     position))))))
  78.       (let loop ((equation (read-line env-port)))
  79.         (if (eof-object? equation)
  80.             #f
  81.             (let ((break (position-of-copula equation))
  82.                   (len (string-length equation)))
  83.               (if (string=? (substring equation 0 break) env-var)
  84.                   (if (= break len)
  85.                       ""
  86.                       (substring equation (+ break 1) len))
  87.                   (loop (read-line env-port)))))))))
  88.  
  89. ;; The LIBRARY-VICINITY procedure returns the pathname of the directory
  90. ;; where Scheme library functions reside.
  91.  
  92. (define library-vicinity
  93.   (let ((library-path (or (getenv "SCHEME_LIBRARY_PATH")
  94.               "/usr/local/lib/slib/")))
  95.     (lambda () library-path)))
  96.  
  97. ;;; (home-vicinity) should return the vicinity of the user's HOME
  98. ;;; directory, the directory which typically contains files which
  99. ;;; customize a computer environment for a user.
  100.  
  101. (define home-vicinity
  102.   (let ((home-path (getenv "HOME")))
  103.     (lambda () home-path)))
  104.  
  105. ;; The OUTPUT-PORT-WIDTH procedure returns the number of graphic characters
  106. ;; that can reliably be displayed on one line of the standard output port.
  107.  
  108. (define output-port-width
  109.   (lambda arg
  110.     (let ((env-width-string (getenv "COLUMNS")))
  111.       (if (and env-width-string
  112.                (let loop ((remaining (string-length env-width-string)))
  113.                  (or (zero? remaining)
  114.                      (let ((next (- remaining 1)))
  115.                        (and (char-numeric? (string-ref env-width-string
  116.                                                        next))
  117.                             (loop next))))))
  118.           (- (string->number env-width-string) 1)
  119.           79))))
  120.  
  121. ;; The OUTPUT-PORT-HEIGHT procedure returns the number of lines of text
  122. ;; that can reliably be displayed simultaneously in the standard output
  123. ;; port.
  124.  
  125. (define output-port-height
  126.   (lambda arg
  127.     (let ((env-height-string (getenv "LINES")))
  128.       (if (and env-height-string
  129.                (let loop ((remaining (string-length env-height-string)))
  130.                  (or (zero? remaining)
  131.                      (let ((next (- remaining 1)))
  132.                        (and (char-numeric? (string-ref env-height-string
  133.                                                        next))
  134.                             (loop next))))))
  135.           (string->number env-height-string)
  136.           24))))
  137.  
  138. ;; *FEATURES* is a list of symbols describing features of this
  139. ;; implementation; SLIB procedures sometimes consult this list to figure
  140. ;; out whether to attempt some incompletely standard operation.
  141.  
  142. (define *features*
  143.   '(source    ; Chez Scheme can load Scheme source files, with the
  144.           ;   command (slib:load-source "filename") -- see below.
  145.  
  146.     compiled  ; Chez Scheme can also load compiled Scheme files, with the
  147.               ;   command (slib:load-compiled "filename") -- see below.
  148.  
  149.     char-ready? delay dynamic-wind fluid-let format
  150.     full-continuation getenv ieee-p1178 macro multiarg/and-
  151.     multiarg-apply pretty-print random random-inexact rationalize
  152.     rev3-procedures rev3-report rev4-optional-procedures rev4-report
  153.     sort string-port system transcript values with-file))
  154.  
  155. ;; Version 5.0c has R4RS macros, but not defmacro.
  156.  
  157. (define *defmacros*
  158.   (list (cons 'defmacro
  159.           (lambda (name parms . body)
  160.         `(set! *defmacros* (cons (cons ',name (lambda ,parms ,@body))
  161.                      *defmacros*))))))
  162. (define (defmacro? m) (and (assq m *defmacros*) #t))
  163.  
  164. (define (macroexpand-1 e)
  165.   (if (pair? e) (let ((a (car e)))
  166.           (cond ((symbol? a) (set! a (assq a *defmacros*))
  167.                      (if a (apply (cdr a) (cdr e)) e))
  168.             (else e)))
  169.       e))
  170.  
  171. (define (macroexpand e)
  172.   (if (pair? e) (let ((a (car e)))
  173.           (cond ((symbol? a)
  174.              (set! a (assq a *defmacros*))
  175.              (if a (macroexpand (apply (cdr a) (cdr e))) e))
  176.             (else e)))
  177.       e))
  178.  
  179. (define base:eval eval)
  180. (define (defmacro:eval x) (base:eval (defmacro:expand* x)))
  181. (define (defmacro:expand* x)
  182.   (require 'defmacroexpand) (apply defmacro:expand* x '()))
  183.  
  184. ;; Chez's sorting routines take parameters in the order opposite to SLIB's.
  185. ;; The following definitions override the predefined procedures with the
  186. ;; parameters-reversed versions.
  187.  
  188. (define chez:sort sort)
  189. (define chez:sort! sort!)
  190. (define chez:merge merge)
  191. (define chez:merge! merge!)
  192.  
  193. (define sort
  194.   (lambda (s p)
  195.     (chez:sort p s)))
  196. (define sort!
  197.   (lambda (s p)
  198.     (chez:sort! p s)))
  199. (define merge
  200.   (lambda (s1 s2 p)
  201.     (chez:merge p s1 s2)))
  202. (define merge!
  203.   (lambda (s1 s2 p)
  204.     (chez:merge! p s1 s2)))
  205.  
  206. ;; Chez's (FORMAT F . A) corresponds to SLIB's (FORMAT #F F . A)
  207.  
  208. (define chez:format format)
  209.  
  210. (define format
  211.   (lambda (where how . args)
  212.     (let ((str (apply chez:format how args)))
  213.       (cond ((not where) str)
  214.         ((eq? where #t) (display str))
  215.         (else (display str where))))))
  216.  
  217. ;; Chez's NIL variable is bound to '(); SLIB's is bound to #F.
  218.  
  219. (define nil #f)
  220.  
  221. ;; SLIB provides identifiers for the TAB (ASCII 9) and FORM-FEED (ASCII 12)
  222. ;; characters.
  223.  
  224. (define slib:tab #\tab)
  225. (define slib:form-feed #\page)
  226.  
  227. ;; The following definitions implement a few widely useful procedures that
  228. ;; Chez Scheme does not provide or provides under a different name.
  229.  
  230. ;; The RENAME-FILE procedure constructs and executes a Unix mv command to
  231. ;; change the name of a file.
  232.  
  233. (define rename-file
  234.   (lambda (src dst)
  235.     (system (string-append "mv " src " " dst))))
  236.  
  237. ;; The CURRENT-ERROR-PORT procedure returns a port to which error
  238. ;; messages are to be displayed; this is the original standard output
  239. ;; port (even if the program subsequently changes the current output port
  240. ;; somehow).
  241.  
  242. (define current-error-port
  243.   (let ((port (current-output-port)))
  244.     (lambda () port)))
  245.  
  246. ;; SLIB provides its own version of the ERROR procedure.
  247.  
  248. (define slib:error
  249.   (lambda args
  250.     (let ((port (current-error-port)))
  251.       (display "Error: " port)
  252.       (for-each (lambda (x) (display x port)) args)
  253.       (error #f ""))))
  254.  
  255. ;; The TMPNAM procedure constructs and returns a temporary file name,
  256. ;; presumably unique and not a duplicate of one already existing.
  257.  
  258. (define tmpnam
  259.   (let ((cntr 100))
  260.     (lambda ()
  261.       (set! cntr (+ 1 cntr))
  262.       (let ((tmp (string-append "slib_" (number->string cntr))))
  263.         (if (file-exists? tmp) (tmpnam) tmp)))))
  264.  
  265. ;; The FORCE-OUTPUT requires buffered output that has been written to a
  266. ;; port to be transferred all the way out to its ultimate destination.
  267.  
  268. (define force-output flush-output)
  269.  
  270. ;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
  271. ;; port versions of CALL-WITH-INPUT-FILE and CALL-WITH-OUTPUT-FILE.
  272.  
  273. (define call-with-output-string
  274.   (lambda (f)
  275.     (let ((outsp (open-output-string)))
  276.       (f outsp)
  277.       (let ((s (get-output-string outsp)))
  278.         (close-output-port outsp)
  279.         s))))
  280.  
  281. (define call-with-input-string
  282.   (lambda (s f)
  283.     (let* ((insp (open-input-string s))
  284.            (res (f insp)))
  285.       (close-input-port insp)
  286.       res)))
  287.  
  288. ;; CHAR-CODE-LIMIT is the number of characters in the character set; only
  289. ;; non-negative integers less than CHAR-CODE-LIMIT are eligible as
  290. ;; arguments to INTEGER->CHAR.
  291.  
  292. (define char-code-limit 256)
  293.  
  294. ;; Chez's MOST-POSITIVE-FIXNUM is a thunk rather than a number.
  295.  
  296. (if (procedure? most-positive-fixnum)
  297.     (set! most-positive-fixnum (most-positive-fixnum)))
  298.  
  299. ;; The IDENTITY procedure returns its argument without change.
  300.  
  301. (define identity 
  302.   (lambda (x) x))
  303.  
  304. ;; The GENTEMP procedure generates unused symbols and marks them as
  305. ;; belonging to the SLIB package.
  306.  
  307. (define gentemp
  308.   (let ((*gensym-counter* -1))
  309.     (lambda ()
  310.       (set! *gensym-counter* (+ *gensym-counter* 1))
  311.       (string->symbol
  312.        (string-append "slib:G" (number->string *gensym-counter*))))))
  313.  
  314. ;; The IN-VICINITY procedure is simply STRING-APPEND, conventionally used
  315. ;; to attach a directory pathname to the name of a file that is expected to
  316. ;; be in that directory.
  317.  
  318. (define in-vicinity string-append)
  319.  
  320. ;; For backward compatability, the SCHEME-FILE-SUFFIX procedure is defined
  321. ;; to return the string ".scm".  Note, however, that ".ss" is a common Chez
  322. ;; file suffix.
  323.  
  324. (define scheme-file-suffix
  325.   (lambda () ".scm"))
  326.  
  327. ;; SLIB appropriates Chez Scheme's EVAL procedure.
  328.  
  329. (define slib:eval eval)
  330. (define macro:eval slib:eval)
  331.  
  332. (define slib:eval-load
  333.   (lambda (<pathname> evl)
  334.     (if (not (file-exists? <pathname>))
  335.         (set! <pathname> (string-append <pathname> (scheme-file-suffix))))
  336.     (call-with-input-file <pathname>
  337.       (lambda (port)
  338.         (let ((old-load-pathname *load-pathname*))
  339.           (set! *load-pathname* <pathname>)
  340.           (do ((o (read port) (read port)))
  341.               ((eof-object? o))
  342.             (evl o))
  343.           (set! *load-pathname* old-load-pathname))))))
  344.  
  345. ;; SLIB:EXIT is the implementation procedure that exits, or returns
  346. ;; if exiting is not supported.
  347.  
  348. (define slib:chez:quit
  349.   (let ((arg (call-with-current-continuation identity)))
  350.     (cond ((procedure? arg) arg)
  351.       (arg (exit))
  352.       (else (exit 1)))))
  353.  
  354. (define slib:exit
  355.   (lambda args
  356.     (cond ((null? args) (slib:chez:quit #t))
  357.       ((eqv? #t (car args)) (slib:chez:quit #t))
  358.       ((eqv? #f (car args)) (slib:chez:quit #f))
  359.       ((zero? (car args)) (slib:chez:quit #t))
  360.       (else (slib:chez:quit #f)))))
  361.  
  362. ;; The SLIB:LOAD-SOURCE procedure, given a string argument, should attach
  363. ;; the appropriate file suffix to the string and load the file named
  364. ;; by the resulting string.
  365.  
  366. (define slib:load-source
  367.   (lambda (f)
  368.     (load (string-append f (scheme-file-suffix)))))
  369.  
  370. ;;; defmacro:load and macro:load also need the default suffix.
  371.  
  372. (define macro:load slib:load-source)
  373.  
  374. ;; The SLIB:LOAD-COMPILED procedure, given a string argument, finds and
  375. ;; loads the file, assumed to have been compiled.
  376.  
  377. (define slib:load-compiled load)
  378.  
  379. ;; SLIB:LOAD can now be defined to load SLIB files.
  380.  
  381. (define slib:load slib:load-source)
  382.  
  383. ;; Load the REQUIRE package.
  384.  
  385. (slib:load (in-vicinity (library-vicinity) "require"))
  386.  
  387. ;; end of chez.init
  388.